from django.shortcuts import render, redirect
from django.views import View
from django.http import HttpResponse, JsonResponse
import os, shutil, uuid, random
from ftp_server.settings import BASE_DIR
from django_redis import get_redis_connection
from . import models
from utlis import restful
from django.views.decorators.http import require_POST
from django.contrib.auth.hashers import make_password, check_password
from functools import wraps
from datetime import datetime
from django.core.paginator import Paginator
from ast import literal_eval  # str列表转为list

# Create your views here.
redis_time = 10800


# 自定义登录装饰器
def check_login(func):
    @wraps(func)
    def wrapper(request, *args, **kwargs):
        item = request.session.get('user', None)
        if item == None:
            return redirect('myadmin:User_Login')
        return func(request, *args, **kwargs)

    return wrapper


# 主页
class IndexView(View):
    def get(self, request):
        return render(request, 'index.html')


@check_login
# 上传 提交数据库
def Upload_Flie(request):
    if request.method == 'GET':
        folder = listdir_nohidden(os.path.join(BASE_DIR, 'static/station'))
        return render(request, 'contact.html', {'folder': folder})
    elif request.method == 'POST':
        name = request.POST.get('name', None)
        redis_con = get_redis_connection('default')
        file_name = redis_con.get("file_name_" + request.session.get('user')).decode()
        # 判断是否上传的是个人空间
        username_list = []
        username = models.User.objects.all().values('username')
        for i in username:
            username_list.append(i['username'])
        if name in username_list:
            if name != request.session.get('user'):
                os.remove(os.path.join(BASE_DIR, 'static/write', file_name))
                return HttpResponse('<script>alert("这是别人的个人空间，请选择自己姓名上传的私密空间");history.back(-1)</script>')
        # 判断文件是否存在
        if models.File_data.objects.filter(default_file_name=file_name).exists():
            os.remove(os.path.join(BASE_DIR, 'static/write', file_name))
            return HttpResponse('<script>alert("文件已存在");history.back(-1)</script>')
        else:
            shutil.move(os.path.join(BASE_DIR, 'static/write/', file_name),
                        os.path.join(BASE_DIR, 'static/station/', name))
            username = models.User.objects.all().values('username')
            username_list = []
            for i in username:
                username_list.append(i['username'])
            models.File_data.objects.create(name=request.session.get('user'), default_file_name=file_name,
                                            file_url=name, download_check=0, permissions=username_list)
            return HttpResponse('<script>alert("上传成功");history.back(-1)</script>')


# 上传接口
def update(request):
    if request.method == 'POST':
        my_file = request.FILES.get("file", None)
        if not my_file:
            return HttpResponse("no files for upload!")
        upload(my_file, request)
        return restful.ok()


# 写入函数
def upload(myfile, request):
    # 存储redis
    redis_con = get_redis_connection('default')
    redis_con.setex("file_name_" + request.session.get('user'), redis_time, myfile.name)
    destination = open(os.path.join(BASE_DIR + '/static/write/', myfile.name), "wb+")
    for chunk in myfile.chunks():  # 分块写入文件
        destination.write(chunk)
    destination.close()
    return


# 页面展示文件夹
@check_login
def File_List(request):
    if request.method == 'GET':
        username_list = []
        # 获取所有用户数据
        username = models.User.objects.all().values('username')
        for i in username:
            username_list.append(i['username'])
        # 将用户数据存储到redis方便后期身份验证
        redis_con = get_redis_connection('default')
        redis_con.setex("redis_all_username", redis_time, str(username_list))

        folder = listdir_nohidden(os.path.join(BASE_DIR, 'static/station', ))
        folder_list = []
        for i in folder:
            if i not in username_list:
                folder_list.append(i)
        # 判断是否是超级管理员
        super = models.User.objects.get(username=request.session.get('user'))

        return render(request, 'about.html',
                      {'count': len(folder_list), 'super': super, 'username_list': username_list})

    elif request.method == 'POST':
        # 获取所有用户数据
        username = models.User.objects.all().values('username')
        username_list = []
        for i in username:
            username_list.append(i['username'])

        folder = listdir_nohidden(os.path.join(BASE_DIR, 'static/station'))
        folder_list = []
        for i in folder:
            if i not in username_list:
                folder_list.append(i)
        page = request.POST.get('page', 1)
        limit = request.POST.get('limit', 10)
        paginator = Paginator(folder_list, limit)
        goodslist = paginator.page(page)

        # 判断是否是管理员来选择是否显示删除按钮
        super = models.User.objects.get(username=request.session.get('user'))
        if super.super_user == 1:
            return JsonResponse({'super_user': 1, "file_data": list(goodslist)})
        else:
            return JsonResponse({'file_data': list(goodslist)})


# 文件夹名字生成器函数
def listdir_nohidden(path):
    for f in os.listdir(path):
        if not f.startswith('.'):
            yield f


# 页面查看文件
@check_login
def File_Views(request):
    if request.method == 'GET':
        file_name = request.GET.get("file_name")
        # 取出redis数据，任何对比文件名是否是个人空间，从而进行身份认证
        redis_con = get_redis_connection('default')
        redis_all_username = redis_con.get("redis_all_username")

        if file_name in redis_all_username.decode():
            if file_name != request.session.get('user', None):
                return HttpResponse('<script>alert("这是人家的底盘你休想看到");history.back(-1)</script>')
        my_space_super = None
        if file_name == request.session.get('user', None):
            my_space_super = 1
        super = models.User.objects.get(username=request.session.get('user'))
        exclude_file = models.File_data.objects.exclude(download_check=1)
        file_count = exclude_file.filter(file_url=file_name).count()
        return render(request, 'file_views.html', {'file_name': file_name, 'super': super, 'file_count': file_count,
                                                   'my_space_super': my_space_super})


    elif request.method == 'POST':
        file_name = request.POST.get("file_name")
        page = request.POST.get('page', 1)
        limit = request.POST.get('limit', 10)
        exclude_file = models.File_data.objects.filter(file_url=file_name).exclude(download_check=1).values(
            "default_file_name", 'name', 'create_time', 'permissions')

        paginator = Paginator(exclude_file, limit)
        goodslist = paginator.page(page)
        check_file = []
        # 验证不同的用户不同查看权限
        for i in goodslist:
            if request.session.get('user') in literal_eval(i['permissions']):
                # 前端模板由于是ajax请求数据拼接，模板不会自动转义，需要手动将数据库datetime类型转换人能看懂的格式
                i['create_time'] = i['create_time'].strftime('%Y-%m-%d %H:%M:%S')
                check_file.append(i)
        # 判断是否 是 管理员账户
        super_dict = {}
        super = models.User.objects.get(username=request.session.get('user'))
        # 判断是否进入个人空间文件夹，是给予删除权限
        my_space_super = None
        if file_name == request.session.get('user', None):
            my_space_super = 1
        if super.super_user == 1:
            super_dict['super'] = 1
            super_dict['file'] = check_file
            super_dict['file_name'] = file_name
            super_dict['my_space_super'] = my_space_super
        else:
            super_dict['file'] = check_file
            super_dict['file_name'] = file_name
            super_dict['my_space_super'] = my_space_super
        return restful.ok(data=super_dict)


# 文件夹删除
def File_Delete(request):
    if request.method == 'GET':
        file_name = request.GET.get("file_name")

        if os.path.exists(os.path.join(BASE_DIR, 'static/station', file_name)):
            shutil.rmtree(os.path.join(BASE_DIR, 'static/station', file_name))
            models_delete = models.File_data.objects.filter(file_url=file_name)
            models_delete.delete()
            logs(request.session.get('user') + '删除了' + file_name + '文件夹')

        return JsonResponse({'code': 200})


# 单个文件删除
def File_One_Delete(request):
    if request.method == 'GET':
        file_name = request.GET.get("file_name")
        file = request.GET.get("file")
        if os.path.exists(os.path.join(BASE_DIR, 'static/station', file_name, file)):
            os.remove(os.path.join(BASE_DIR, 'static/station', file_name, file))
            models_delete = models.File_data.objects.filter(default_file_name=file)
            models_delete.delete()

            # # 判断文件夹是否为空，为空删除
            # if listdir_nohidden(os.path.join(BASE_DIR, 'static/station', file_name)):
            #     os.rmdir(os.path.join(BASE_DIR, 'static/station', file_name))
            logs(request.session.get('user') + '删除了' + file_name + '文件夹' + '下的' + file + '文件')

        return JsonResponse({'code': 200})


# 文件搜索
def File_Search(request):
    if request.method == 'GET':
        input1 = request.GET.get("input1")
        file_url = models.File_data.objects.filter(file_url__icontains=input1).values("file_url")
        file_list = []
        for i in file_url:
            if i not in file_list:
                file_list.append(i)
        return restful.ok('搜索成功', data=file_list)


# 登录
def User_Login(request):
    if request.method == 'GET':
        return render(request, 'login.html')

    elif request.method == 'POST':
        name = request.POST.get("name")
        password = request.POST.get("pass")
        check_user = models.User.objects.filter(username=name).exists()
        if check_user:
            models_password = models.User.objects.get(username=name)
            check = check_password(password, models_password.password)
            if check:
                request.session['user'] = str(models_password)
                request.session['user_id'] = str(uuid.uuid4())
                return restful.ok("登录成功")
            else:
                return restful.params_error("小主，密码错误")
        else:
            return restful.params_error("小主，此账号不存在")


# 注册
@require_POST
def User_Register(request):
    regname = request.POST.get("regname")
    regpass = request.POST.get("regpass")
    regpass = make_password(regpass, None, 'pbkdf2_sha256')
    models.User.objects.create(username=regname, password=regpass, super_user=0)
    return restful.ok("注册成功")


# 退出
def User_Logout(request):
    request.session.delete()
    return restful.ok()


# 修改密码
@check_login
def Check_Password(request):
    if request.method == 'GET':
        return render(request, 'check_password.html')
    elif request.method == 'POST':
        New_Password = request.POST.get('New_Password')
        user = request.POST.get('user')
        user_data = models.User.objects.get(username=user)
        New_pass = make_password(New_Password, None, 'pbkdf2_sha256')
        user_data.password = New_pass
        user_data.save()
        return restful.ok()


# 进入权限管理页面判断是否有权限
@check_login
def User_Permissions(request):
    if request.method == 'GET':
        try:
            user = request.session.get('user', None)
            models_user = models.User.objects.get(username=user)
            if models_user.super_user == 0:
                return HttpResponse('<script>alert("无权限访问");history.back(-1)</script>')
            elif models_user.super_user == 1:
                file = listdir_nohidden(os.path.join(BASE_DIR, 'static/station', ))
                return render(request, 'super_update.html', {'file': file})
        except:
            return redirect('/')


# layui 表格自动获取数据接口
def check_file_data(request):
    # 获取搜索条件
    file_name = request.GET.get('file_name', None)
    file_data = ''
    data_count = ''

    db_username = models.User.objects.all().values('username')
    # 判断是否有搜索条件
    if file_name:
        file_data = models.File_data.objects.filter(default_file_name__icontains=file_name).order_by('id')
        for i in db_username:
            file_data = file_data.exclude(file_url=i['username'])
        data_count = len(file_data)
    else:
        file_data = models.File_data.objects.all().order_by('id')
        for i in db_username:
            file_data = file_data.exclude(file_url=i['username'])
        data_count = len(file_data)
    page = request.GET.get('page', None)
    limit = request.GET.get('limit', None)  # 一页多少数据
    p = Paginator(file_data, limit)
    page_data = p.page(page)  # 获取当前页数据
    data_list = []
    # 此循环数据重组
    for i in page_data:
        data_dict = {}
        if i.download_check == 0:
            i.download_check = '有权限'
        elif i.download_check == 1:
            i.download_check = '无权限'
        data_dict.update(file_url=i.file_url, default_file_name=i.default_file_name,
                         create_time=i.create_time.strftime('%Y-%m-%d %H:%M:%S'), download_check=i.download_check)
        data_list.append(data_dict)
    return JsonResponse({'code': 0, "msg": "", "count": data_count, "data": data_list})


# 修改文件夹名字
def Update_File_Name(request):
    file_name = request.GET.get('file_name')
    new_file_name = request.GET.get('new_file_name')
    # 数据库修改
    models.File_data.objects.filter(file_url=file_name).update(file_url=new_file_name)
    # 本地存储修改
    os.rename(os.path.join(BASE_DIR, 'static/station', file_name),
              os.path.join(BASE_DIR, 'static/station', new_file_name))
    logs(request.session.get('user') + '把' + file_name + '文件夹' + '重命名为' + new_file_name)

    return restful.ok()


# 修改文件名字
def Update_Name(request):
    name = request.GET.get('name', None)
    new_name = request.GET.get('new_name', None)
    file_name = request.GET.get('file_name', None)
    # 数据库修改
    models.File_data.objects.filter(default_file_name=name).update(default_file_name=new_name)
    # 本地文件修改
    os.rename(os.path.join(BASE_DIR, 'static/station', file_name, name),
              os.path.join(BASE_DIR, 'static/station', file_name, new_name))
    logs(request.session.get('user') + '把' + name + '文件' + '重命名为' + new_name)
    return restful.ok()


# 锁定下载工程文件夹权限
def Lock_Download_File(request):
    file_url = request.GET.get("file_url")
    models.File_data.objects.filter(file_url=file_url).update(download_check=1)
    logs(request.session.get('user') + '锁定了' + file_url + '文件夹')
    return restful.ok()


# 解锁下载工程文件夹权限
def Unlock_Download_File(request):
    file_url = request.GET.get("file_url")
    models.File_data.objects.filter(file_url=file_url).update(download_check=0)
    logs(request.session.get('user') + '解锁了' + file_url + '文件夹')
    return restful.ok()


# 锁定下载文件权限
def lock_File(request):
    default_file_name = request.GET.get('default_file_name')
    models.File_data.objects.filter(default_file_name=default_file_name).update(download_check=1)
    logs(request.session.get('user') + '锁定了' + default_file_name + '文件')
    return restful.ok()


# 解锁下载文件权限
def Unlock_File(request):
    default_file_name = request.GET.get('default_file_name')
    models.File_data.objects.filter(default_file_name=default_file_name).update(download_check=0)
    logs(request.session.get('user') + '解锁了' + default_file_name + '文件')
    return restful.ok()


# 日志
def logs(content):
    # 1. 使用open()打开指定文件
    with open('/www/FTP_SERVER/write_ operation/ftp_server.txt', 'a') as fp:
        # 2. 对文件进行写入操作
        fp.write(content + ',操作时间是' + str(datetime.now()) + "\n")
        fp.flush()
    return


# 创建文件夹
def Create_File(request):
    create_file = request.GET.get('create_file')
    if create_file is '':
        return restful.params_error('请输入创建文件夹的名字')
    try:
        os.mkdir(os.path.join(BASE_DIR, 'static/station/', str(create_file)))
        return restful.ok("创建成功")
    except FileExistsError as error:
        return restful.params_error("{}此文件夹已存在".format(create_file))


# 修改管理员权限
def update_super_permissions(request):
    user_data = request.GET.dict()
    redis_con = get_redis_connection('default')
    try:
        if user_data['email_code']:
            user_uuid = redis_con.get(request.session.get('user_id') + 'sms_code')
            if user_data['email_code'] != user_uuid.decode():
                return restful.params_error('验证码错误，请重新尝试')
    except KeyError as e:
        return restful.params_error('请输入邮箱验证码')
    del user_data['email_code']
    for name in user_data.values():
        models.User.objects.filter(username=name).update(super_user=1)
    return restful.ok('添加管理员成功')


# 加载管理员和普通用户信息
def load_super_permissions(request):
    user = models.User.objects.filter(super_user=0).values('id', 'username', 'super_user')
    user_list = []
    for i in user:
        i['disabled'] = ''
        user_list.append(i)
    super_user = models.User.objects.filter(super_user=1).values('id', 'username', 'super_user')
    super_user_list = []
    check_user = []
    for i in super_user:
        if i['username'] == '张彬' or i['username'] == '陈欢':
            i['disabled'] = 'True'
        else:
            i['disabled'] = ''
        check_user.append(i['id'])
        super_user_list.append(i)
    user_list = user_list + super_user_list
    return restful.ok(user=user_list, check_user=check_user)


from django.core.mail import send_mail


@check_login
# 发送邮件
def send_email(request):
    sms_code = "%06d" % random.randint(0, 999999)
    send_mail('力邦测控注册码', '您的校验码:{}，您正在注册成为超级管理员，若非本人操作，请勿泄露，感谢您的支持！(十分钟后内有效)'.format(sms_code), 'chyfb200428@163.com',
              ['chyfb200428@163.com'], fail_silently=False)
    # 存储redis
    redis_con = get_redis_connection('default')
    redis_con.setex(request.session.get('user_id') + 'sms_code', 600, sms_code)
    return restful.ok('已发送')


# 删除管理员
def delete_super_permissions(request):
    user_data = request.GET.dict()
    redis_con = get_redis_connection('default')
    try:
        if user_data['email_code']:
            user_uuid = redis_con.get(request.session.get('user_id') + 'sms_code')
            if user_data['email_code'] != user_uuid.decode():
                return restful.params_error('验证码错误，请重新尝试')
    except KeyError as e:
        return restful.params_error('请输入邮箱验证码')
    del user_data['email_code']
    for name in user_data.values():
        models.User.objects.filter(username=name).update(super_user=0)
    return restful.ok('删除管理员成功')


# super二级联动框文件接口
def select_frame(request):
    file = request.GET.get('nos')
    file_dict = {}
    exclude_file = models.File_data.objects.exclude(download_check=1)
    file_name = exclude_file.filter(file_url=file).values("default_file_name")
    file_dict[file] = list(file_name)
    return restful.ok(data=file_dict)


# 联动框动态渲染穿俊框管理员
def user_file_permissions(request):
    user_file = request.GET.get('user_file')
    models_file = models.File_data.objects.get(default_file_name=user_file)
    # 取出来的数据是str类型列表需要转换成list类型方便操作，literal_eval和eval都可以达到效果，不过literal_eval会考虑安全性选择执行
    res_list = literal_eval(models_file.permissions)
    username = models.User.objects.all().values('username')
    leftCheck = []
    rightCheck = []
    for i in username:
        if i['username'] in res_list:
            rightCheck.append(i['username'])
        else:
            leftCheck.append(i['username'])
    return restful.ok('获取' + user_file + '文件用户成功', leftCheck=leftCheck, rightCheck=rightCheck)


# 文件 不用用户不同查看权限 修改用户权限函数
def transfer_box_add_user(request):
    user_dict = request.GET.dict()
    file_name = user_dict['file_name']
    del user_dict['file_name']
    models_user_list = []
    for name in user_dict.values():
        models_user_list.append(name)
    if models_user_list:
        models.File_data.objects.filter(default_file_name=file_name).update(permissions=models_user_list)
        return restful.ok()
    else:
        return restful.params_error('请先选择文件夹和文件，获取用户权限信息')


# 整个文件 不用用户不同查看权限 修改用户权限函数
def transfer_box_add_file_user(request):
    user_dict = request.GET.dict()
    file = user_dict['file_name']
    del user_dict['file_name']
    models_user_list = []
    for name in user_dict.values():
        models_user_list.append(name)
    if models_user_list:
        models.File_data.objects.filter(file_url=file).update(permissions=models_user_list)
        return restful.ok()
    else:
        return restful.params_error('请先选择文件，获取用户权限信息')
